// 引入模块
const Koa = require('koa');
const router = require('koa-router')(); /*引入是实例化路由 推荐*/
const render = require('koa-art-template');
const path = require('path');
const fs = require('fs');
const koaBody = require('koa-body');
const DB = require('./module/db.js');
const static = require('koa-static')
const cors = require('koa2-cors');

// 实例化
let app = new Koa();

// 允许跨域访问
app.use(cors({
  exposeHeaders: ['WWW-Authenticate', 'Server-Authorization', 'Date'],
  maxAge: 100,
  credentials: true,
  allowMethods: ['GET', 'POST', 'OPTIONS'],
  allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Custom-Header', 'anonymous'],
}));

const uploadUrl = "http://localhost:4000/upload";
// 配置post提交数据的中间件
app.use(koaBody({
  multipart: true, // 支持文件上传
  formidable: {
    maxFieldsSize: 10 * 1024 * 1024, // 最大文件为10兆
    multipart: true // 是否支持 multipart-formdate 的表单
  }
}));

// 配置 koa-art-template 模板引擎
render(app, {
  root: path.join(__dirname, 'views'), // 视图的位置
  extname: '.html', // 后缀名
  debug: process.env.NODE_ENV !== 'production' // 是否开启调试模式
})

// 配置静态web服务的中间件
// app.use(static('static'));
app.use(static(__dirname + '/static'))
app.use(static(__dirname + '/public')) // koa静态资源中间件可以配置多个


/**
 * flag: 是否是多个文件上传
 */
const uploadFilePublic = function (ctx, files, flag) {
  const filePath = path.join(__dirname, '/static/upload/');
  let file,
    fileReader,
    fileResource,
    writeStream;

  const fileFunc = function (file) {
    // 读取文件流
    fileReader = fs.createReadStream(file.path);
    // 组装成绝对路径
    fileResource = filePath + `/${file.name}`;
    /*
     使用 createWriteStream 写入数据，然后使用管道流pipe拼接
    */
    writeStream = fs.createWriteStream(fileResource);
    fileReader.pipe(writeStream);
  };
  const returnFunc = function (flag) {
    if (flag) {
      let url = '';
      for (let i = 0; i < files.length; i++) {
        url += uploadUrl + `/${files[i].name},`
      }
      url = url.replace(/,$/gi, "");
      ctx.body = {
        url: url,
        code: 0,
        message: '上传成功'
      };
    } else {
      ctx.body = {
        url: uploadUrl + `/${files.name}`,
        code: 0,
        message: '上传成功'
      };
    }
  };
  if (flag) {
    // 多个文件上传
    for (let i = 0; i < files.length; i++) {
      const f1 = files[i];
      fileFunc(f1);
    }
  } else {
    fileFunc(files);
  }

  // 判断 /static/upload 文件夹是否存在，如果不在的话就创建一个
  if (!fs.existsSync(filePath)) {
    fs.mkdir(filePath, (err) => {
      if (err) {
        throw new Error(err);
      } else {
        returnFunc(flag);
      }
    });
  } else {
    returnFunc(flag);
  }
}

// 富文本编辑器图片上传
const uploadFileWang = function (ctx, files) {
  const filePath = path.join(__dirname, '/static/upload/');
  let file,
    fileReader,
    fileResource,
    writeStream;

  const fileFunc = function (file) {
    // 读取文件流
    fileReader = fs.createReadStream(file.path);
    // 组装成绝对路径
    fileResource = filePath + `/${file.name}`;
    /*
     使用 createWriteStream 写入数据，然后使用管道流pipe拼接
    */
    writeStream = fs.createWriteStream(fileResource);
    fileReader.pipe(writeStream);
  };
  const returnFunc = function () {

    let data = [];
    for (let i = 0; i < files.length; i++) {
      let url = uploadUrl + `/${files[i].name}`
      data.push({
        url: url,
        alt: "图片文字说明",
        href: url
      })
    }

    ctx.body = {
      // errno 即错误代码，0 表示没有错误。
      //       如果有错误，errno != 0，可通过下文中的监听函数 fail 拿到该错误码进行自定义处理
      "errno": 0,

      // data 是一个数组，返回图片Object，Object中包含需要包含url、alt和href三个属性,它们分别代表图片地址、图片文字说明和跳转链接,alt和href属性是可选的，可以不设置或设置为空字符串,需要注意的是url是一定要填的。
      "data": data
    };

  };

  // 多个文件上传
  for (let i = 0; i < files.length; i++) {
    const f1 = files[i];
    fileFunc(f1);
  }


  // 判断 /static/upload 文件夹是否存在，如果不在的话就创建一个
  if (!fs.existsSync(filePath)) {
    fs.mkdir(filePath, (err) => {
      if (err) {
        throw new Error(err);
      } else {
        returnFunc();
      }
    });
  } else {
    returnFunc();
  }
}


// 上传单个或多个文件
router.post('/upload', (ctx) => {
  let files = ctx.request.files.file;
  if (files.length === undefined) {
    // 上传单个文件，它不是数组，只是单个的对象
    uploadFilePublic(ctx, files, false);
  } else {
    uploadFilePublic(ctx, files, true);
  }
});

// 上传单个或多个文件
router.post('/uploadWang', (ctx) => {
  let files = ctx.request.files;
  let fileArray = []
  Object.keys(files).map(key => {
    fileArray.push(files[key])
  })
  uploadFileWang(ctx, fileArray);
});


// 显示学员信息
router.get('/', async (ctx) => {
  let result = await DB.find('user', {});
  await ctx.render('index', {
    list: result
  });
})

// 增加学员
router.get('/add', async (ctx) => {
  await ctx.render('add');
})

// 执行增加学员的操作
router.post('/doAdd', async (ctx) => {
  // 获取表单提交的数据
  // console.log(ctx.request.body); // { name: 'aaa', age: 'aa', sex: 'a' }
  let data = await DB.insert('user', ctx.request.body);
  console.log(data);

  try {
    if (data.acknowledged) {
      ctx.redirect('/');
    }
  } catch (err) {
    console.log(err);
    ctx.redirect('/add');
  }
})

// 编辑学员
router.get('/edit', async (ctx) => {
  // 通过 get 传过来的 id 来获取用户信息
  let id = ctx.query.id;
  // 获取用户信息
  let data = await DB.find('user', { "_id": DB.getObjectId(id) });
  console.log(data);

  await ctx.render('edit', {
    list: data[0]
  });
})

router.post('/doEdit', async (ctx) => {
  // 获取用户信息
  // console.log(ctx.request.body);
  var id = ctx.request.body.id;
  var username = ctx.request.body.username;
  var age = ctx.request.body.age;
  var sex = ctx.request.body.sex;

  let data = await DB.update('user', { "_id": DB.getObjectId(id) }, {
    username, age, sex
  })

  try {
    if (data.acknowledged) {
      ctx.redirect('/')
    }
  } catch (err) {
    console.log(err);
    ctx.redirect('/edit');
  }
})

// 删除学员
router.get('/delete', async (ctx) => {
  let id = ctx.query.id;
  let data = await DB.remove('user', { "_id": DB.getObjectId(id) });
  console.log(data);

  if (data) {
    ctx.redirect('/');
  }
})



app.use(router.routes());
app.use(router.allowedMethods());

app.listen(4000);